package ch.zhaw.skuh.turing.model.turingmaschine.rules;

import ch.zhaw.skuh.turing.model.turingmaschine.Subtraction_N_ary;

public class SubtractionRuleSet extends AdditionRuleSet {

	protected static int COUNTSTATES = Subtraction_N_ary.COUNTSTATES;

	public SubtractionRuleSet(Subtraction_N_ary tc) {
		super(tc);
	}

	// run forward, check for non-zero in t2
	private void addRule_checkZero(int q, int exitNormal, int exitSpecial,
			int[] tapes) {
		int e = exitNormal;
		// t1 and t3 are blank

		// t2 is zero, delete --> continue
		tc.addRulePadded(q, "_0_", q, "___", "110", tapes);

		// all zero's deleted --> exit exitSpecial
		tc.addRulePadded(q, "___", exitSpecial, "___", "000", tapes);

		// iT2 starts at 1 !!
		for (int iT2 = 1; iT2 < tc.getRadix(); iT2++) {
			String t2 = Integer.toString(iT2, tc.getRadix());
			// non-zero found, --> exit
			tc.addRulePadded(q, "_" + t2 + "_", e, "_" + t2 + "_", "110", tapes);
		}
	}

	@Override
	// subtract t1+t3 from t2
	protected String getNewValues(int t1, int t2, int t3) {
		int diff = t2 - t1 - t3;
		String o = "_";
		if (diff < 0) {
			o = "1";
			diff += tc.getRadix();
		}
		// new value in tape 2
		String n = Integer.toString(diff, tc.getRadix());
		// t1 is blank, t3 has overrun
		return "_" + n + o;
	}

	@Override
	protected final void addRulesPart_Blank1_2(int q, int exitNormal, int exitSpecial,
			int[] tapes, String tOld, String tNew) {
		// *** new first digit from overrun *** negative number
		// this has its own exit state
		// --> exit overrun
		//tc.addRulePadded(q, "__1", exitSpecial, "___", "110", tapes);
		// do nothing, this should not happen!! Negative number !!!
	}
	

	@Override
	protected void addRulesPart_Blank1_3(int q, int exitNormal,
			int exitSpecial, int[] tapes, String tOld, String tNew) {
		// run backwards on leading zero
		if (tNew.compareTo("_0_") == 0) {
			// --> continue
			tc.addRulePadded(q, tOld, q, tNew, "-1-10", tapes);
		} else {
			// --> exit
			tc.addRulePadded(q, tOld, exitSpecial, tNew, "110", tapes);
		}
	}
	
	@Override
	protected final void addRulesPart_Blank2_3(int q, int exitNormal, int exitSpecial,
			int[] tapes, String tOld, String tNew) {
		// do nothing, this should not happen!! Negative number !!!
	}

	@Override
	protected void addRulesPart_Blank1(int q, int exitNormal, int exitSpecial, int[] tapes,
			String tOld, String tNew) {
		
		//check leading zero
		if (tNew.substring(1).compareTo("0_") == 0) {
			// --> continue
			tc.addRulePadded(q, tOld, q, tNew, "-1-10", tapes);
		} else if (tNew.substring(2).compareTo("_") == 0){
			// non-zero in t2 --> exit special
			tc.addRulePadded(q, tOld, exitSpecial, tNew, "110", tapes);
		} else {
			// new overrun --> continue
			tc.addRulePadded(q, tOld, q, tNew, "-1-10", tapes);
		}
	}

	@Override
	public int setRules(int minState, int exitNormal, int exitSpecial, int[] tapes) {
		return setSubtractionRules(minState, exitNormal, exitSpecial, tapes);
	}
	
	protected int setSubtractionRules(int minState, int exitNormal, int exitSpecial, int[] tapes) {

		// *** subtraction rules ***

		// everything in tapes 1, 2 and 3
		int[] tapesCurrent = new int[] { tapes[0], tapes[1], tapes[2] };

		// *** q0 rules ***
		// run backwards, subtract tape 1+3 from t2 to t3 and put
		// temporary overrun to tape 3
		addRule_AdditionSubtraction(minState + 0, minState + 1, exitNormal,
				tapesCurrent);

		// *** q1 rules ***
		// run forwards, check for first non-zero char
		addRule_checkZero(minState + 1, exitNormal, exitSpecial, tapesCurrent);

		// loaded rule-set, return new minState
		return minState + COUNTSTATES;
	}
}
